﻿using System.ComponentModel;
using System.Threading;
using UnityEngine;
using UnityEngine.UI;

public class TestThreadUI : MonoBehaviour {

	public Button StartButton;
    public Button CancelButton;
    public Slider ValueSlider;
    public Text InfoText;

    private BackgroundWorker bw = new BackgroundWorker();

    void Start () {
        if (null != StartButton)
        {
            StartButton.onClick.AddListener(OnButtonStart);
            StartButton.interactable = true;
        }

        if (null != CancelButton)
        {
            CancelButton.onClick.AddListener(OnButtonCancel);
            CancelButton.interactable = false;
        }

        if (null != ValueSlider)
        {
            ValueSlider.minValue = 0;
            ValueSlider.maxValue = 100;
            ValueSlider.value = 0;
        }

        if (null != InfoText)
        {
            InfoText.text = "";
        }

        bw.WorkerReportsProgress = true;
        bw.WorkerSupportsCancellation = true;

        bw.DoWork += OnDoWork;
        bw.ProgressChanged += OnProgressChanged;
        bw.RunWorkerCompleted += OnRunWorkerCompleted;
    }
	
	void Update () {
		
	}    

    public void OnButtonStart()
    {
        StartButton.interactable = false;
        CancelButton.interactable = true;

        bw.RunWorkerAsync("param");
    }

    public void OnButtonCancel()
    {
        CancelWorker();

        StartButton.interactable = true;
        CancelButton.interactable = false;
    }

    private void OnRunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        //必须判断标志，否则由于关闭程序而取消了线程操作
        //但线程在真正取消前，Text可能已经被Unity引擎销毁了
        //这时再访问InfoText就可能出现空指针错误
        if(!e.Cancelled)
        {
            InfoText.text = "Work Completed.";

            StartButton.interactable = true;
            CancelButton.interactable = false;
        }        
    }

    private void OnProgressChanged(object sender, ProgressChangedEventArgs e)
    {
        ValueSlider.value = e.ProgressPercentage;
        InfoText.text = "" + e.ProgressPercentage;
    }

    private void OnDoWork(object sender, DoWorkEventArgs e)
    {
        BackgroundWorker worker = (BackgroundWorker)sender;

        for (int i = 0; i <= 100; i++)
        {
            Thread.Sleep(50);

            //判断线程是否被用户取消了
            if (worker.CancellationPending)
            {
                e.Cancel = true;
                break;
            }

            worker.ReportProgress(i);
        }
    }

    void CancelWorker()
    {
        if (null != bw)
        {
            bw.CancelAsync();
        }
    }

    #region 下列三种情况可以取消线程的运行
    //1 第一个触发
    private void OnApplicationQuit()
    {
        Debug.Log("OnApplicationQuit");
        CancelWorker();
    }

    //2 第二个触发
    private void OnDisable()
    {
        Debug.Log("OnDisable");
        CancelWorker();
    }

    //3 第三个触发
    private void OnDestroy()
    {
        Debug.Log("OnDestroy");
        CancelWorker();
    }
    #endregion
}
